package epoch.game.core.distr.netty;

import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.Logger;

import epoch.game.core.common.Loggers;
import epoch.game.core.distr.INodeChannel;
import epoch.game.core.distr.Node;
import epoch.game.core.distr.RemoteNode;
import epoch.game.core.netty.NettySession;
import epoch.game.core.server.ISession;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.EventLoop;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

public class NodeOutboundHandler extends ChannelInboundHandlerAdapter{
	private final Logger log = Loggers.CORE_LOGGER;
	Node node;
	RemoteNode remote;
	INodeChannel nodeChannel;

	private static final AttributeKey<ISession> SESSION_KEY = AttributeKey.newInstance("session");

	public NodeOutboundHandler(RemoteNode remote) {
		this.remote = remote;
		this.node = remote.getLocalNode();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		final EventLoop eventLoop = ctx.channel().eventLoop();
		eventLoop.schedule(new Runnable() {
			@Override
			public void run() {
				remote.connect();
			}
		}, 1L, TimeUnit.SECONDS);
		super.channelInactive(ctx);
		ISession session = getSession(ctx);
		if(session==null) {
			return;
		}
		nodeChannel.onSessionClosed(session);
	}

	private ISession getSession(ChannelHandlerContext ctx) {
		Attribute<ISession> attr = ctx.channel().attr(SESSION_KEY);
		if (attr == null) {
			return null;
		}
		ISession session = attr.get();
		return session;
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		// 记录数据
		ISession session = getSession(ctx);
		if(session==null) {
			return;
		}
		byte[] bytes = (byte[]) msg;
		nodeChannel.onMessageReceived(session, bytes);
	}

	/**
	 * 建立新连接
	 * 
	 * @throws Exception
	 */
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		NettySession session = new NettySession(ctx.channel());
		session.remoteIP();
		ctx.channel().attr(SESSION_KEY).set(session);
		// 创建连接的时候将IP和端口保存起来
		nodeChannel.onSessionCreated(session);
	}

	/**
	 * 有异常发生
	 * 
	 * @throws Exception
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		super.exceptionCaught(ctx, cause);
		ISession session = getSession(ctx);
		if(session!=null) {
			nodeChannel.onExceptionCaught(session, cause);
		}
		// 输出错误日志
		log.error("连接发生异常：remoteId={}, remoteName={}, exception={}", remote.getId(), remote.getName(), cause.getMessage());
		
	}
	
}
